package utils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * save the running memory
 * @author Evan
 *
 */
public class StringUtils {

	private static List<MyStringBuffer> list_idle=new ArrayList<MyStringBuffer>(0);
	
	private static Map<Integer,MyStringBuffer> map_used =new HashMap<Integer,MyStringBuffer>(0);
	
	private static final StringBuffer sb_temp = new StringBuffer();
	
	private static final List<Character> base64 = new ArrayList<Character>();
	static{
		for(int i='A';i<='Z';i++){
			base64.add((char)i);
		}
		for(int i='a';i<='z';i++){
			base64.add((char)i);
		}
		for(int i='0';i<='9';i++){
			base64.add((char)i);
		}
		base64.add('/');
		base64.add('.');
	}
	
	// --------------------------------------------------------------------------------
	public static class MyStringBuffer{
		private static int index=0;
		private int index_used;
		
		private int lastLength;
		
		
		private StringBuffer sb = new StringBuffer();
		private MyStringBuffer() {
			index++;
			this.index_used=index;
		}
		private void init(){
			lastLength=0;
		}
		/**
		 * the last used method
		 * @param obj
		 * @return
		 */
		public MyStringBuffer put(Object obj){
			String str = obj==null?"null":obj.toString();
			sb.append(str);
			lastLength = str.toString().length();
			return this;
		}
		public String popLast(){
			String str = sb.substring(sb.length()-lastLength, sb.length());
			sb.delete(sb.length()-lastLength, sb.length());
			
			return str;
		}
		
		public MyStringBuffer add(Object obj){
			return put(obj);
		}
		
		public MyStringBuffer addEnter(){
			return println("");
		}
		/**
		 * 
		 * @param obj, if obj is "", add a blank, if not, append a blank to obj
		 * @return
		 */
		public MyStringBuffer addBlank(Object obj){
			return add(obj).add(" ");
		}
		public MyStringBuffer push(Object obj){
			return put(obj);
		}
		public MyStringBuffer print(Object obj){
			return put(obj);
		}
		public MyStringBuffer println(Object obj){
			print(obj);
			sb.append("\r\n");
			lastLength+=2;
			return this;
		}
		
		public String getStringAndClose(){
			String result = sb.toString();
			sb.delete(0, sb.length());
			list_idle.add(map_used.remove(this.index_used));
			return result;
		}
		
		@Override
		public String toString() {
			return getStringAndClose();
		}
		
		@Override
		public boolean equals(Object obj) {
			return this.sb.equals(obj);
		}
		@Override
		public int hashCode() {
			return this.sb.hashCode();
		}
		public int getIndex_used() {
			return index_used;
		}
		
	}
	// --------------------------------------------------------------------------------
	/**
	 * add 3 element into list
	 */
	private static  void addElement(){
		list_idle.add(new MyStringBuffer());
	}
	
	/**
	 * get an idle string buffer from the pool
	 * @return
	 */
	public static synchronized MyStringBuffer getNewMyStringBuffer(){
		if(list_idle.size()==0) addElement();
		
		MyStringBuffer msb = list_idle.remove(list_idle.size()-1);
		
		map_used.put(msb.getIndex_used(),msb);
		msb.init();
		return msb;
	}
	
	public static String getMyStringBufferInstanceSize(){
		sb_temp.delete(0, sb_temp.length());
		
		sb_temp.append(list_idle.size()+map_used.size()).append(" - idle: ").append(list_idle.size()).append(", used: ").append(map_used.size());
		
		return sb_temp.toString();
	}
	
	
	
	public static char baseCheck(char ch){
		char ch_new = ch;
		
		if(!base64.contains(ch)) ch_new = base64.get(ch%base64.size());
		
		return ch_new;
	}
	
	public static String baseReplace(String str){
		
		char[] chs = str.toCharArray();
		
		for(int i=0;i<chs.length;i++){
			chs[i] = baseCheck(chs[i]);
		}
		
		return new String(chs);
	}
	
	public static int[] getUnicodeFromString(String str){
		IntStack is = new IntStack();
		for(char ch: str.toCharArray()){
			is.addInt(ch);
		}
		return is.getIntArray();
	}
	
	public static String getFormattedUnicodeString(String str){
		MyStringBuffer msb = StringUtils.getNewMyStringBuffer();
		
		for(char ch : str.toCharArray()){
			int unicode = ch;
			String unicode_str = "0000"+Integer.toHexString(unicode);
			unicode_str = unicode_str.substring(unicode_str.length()-4).toUpperCase();
			msb.put(unicode_str);
		}
		
		return msb.getStringAndClose();
	}
	
	
	public static void main(String[] args) {
		
		System.out.println(getFormattedUnicodeString("hello"));
		
	}
	
	
	
}
